#ifndef QTEST_TIME_SERIES_H_
#define QTEST_TIME_SERIES_H_

/**
 * @file QTest_TimeSeries.h
 */

#include <QtGui/QApplication>
#include <QtCore/QObject>
#include <QtTest/QtTest>

#include "clean/Spectrum.h"
#include "clean/SpectrumProcessing.h"
#include "clean/Clean.h"
#include "TimeSeries.h"

#include "widgets/plotting/ScatterPlot.h"
#include <qwt_plot.h>

#include <QtCore/QVector>
#include <vector>

using namespace std;
using namespace spectClean;

class QTest_CleanTimeSeries : public QObject
{
    private:
        Q_OBJECT

    public:
        QTest_CleanTimeSeries() {}
        ~QTest_CleanTimeSeries() {}

    private slots:
        void test()
        {
            // ======== TIME SERIES ============================================
            TimeSeries t;
            typedef SpectrumComponent fc; // (amp, frequency)
            std::vector<fc> components;
            components.push_back(fc(1.0, 4.2));
            components.push_back(fc(0.6, 15.0));
            t.generateRandom(70, 0.0, 2.0, components);
            //t.generateEven(500, 0.0, 1.2, components);

//            _s.push_back(new ScatterPlot);
//            _s.back()->setSamples(&t.time()[0], &t.amp()[0], t.size());
//
//            _p.push_back(new QwtPlot);
//            _p.back()->setMinimumSize(500, 500);
//            _p.back()->setVisible(true);
//            _s.back()->attach(_p.back());
//            _p.back()->setTitle("time series");


            // ======== DIRTY SPECTRUM =========================================
            const double max_freq = 20.0;
            const unsigned oversample = 11;
            Spectrum ds;
            SpectrumProcessing sp;
            sp.dirtySpectrumDFT(t, ds, max_freq, oversample);

            QVector<double> amp(ds.size());
//            for (unsigned i = 0; i < ds.size(); ++i)
//                amp[i] = fabs(ds.amp()[i]);
//
//            _s.push_back(new ScatterPlot);
//            _s.back()->setPlotStyle(ScatterPlot::LINE_DOT);
//            _s.back()->setSamples(&ds.freq()[0], amp.data(), ds.size());
//
//            _p.push_back(new QwtPlot);
//            _p.back()->setMinimumSize(1000, 500);
//            _p.back()->setVisible(true);
//            _s.back()->attach(_p.back());
//            _p.back()->setAxisScale(QwtPlot::xBottom, -max_freq, max_freq);
//            _p.back()->setTitle("dirty spectrum");


            // ======== WINDOW SPECTRUM ========================================
            Spectrum ws;
            sp.windowSpectrumDFT(t, ws, max_freq * 2.0, oversample);



            // ======== CLEAN ==================================================
            Spectrum cc;
            Spectrum residual;
            residual = ds;
            cc.resize(residual.size());
            cc.freq() = ds.freq();
            int num_iter = 50;
            double gain = 0.25;
            Clean c;

            _p.push_back(new QwtPlot);
            _p.back()->setMinimumSize(1000, 500);
            _p.back()->setVisible(true);
            _s.push_back(new ScatterPlot);
            _s.back()->attach(_p.back());
            _s.back()->setPlotStyle(ScatterPlot::LINE_DOT);
            _p.back()->setAxisScale(QwtPlot::xBottom, -max_freq, max_freq);
            _p.back()->setAxisScale(QwtPlot::yLeft, 0.0, 0.6);
            _p.back()->setTitle("residual spectrum");
            _p.back()->setVisible(true);
            _s.back()->attach(_p.back());
            amp.resize(residual.size());
            double * a = &amp[0];
            Spectrum::Complex * ra = &residual.amp()[0];
            QTest::qWaitForWindowShown(_p.back());
            _p.back()->setAutoReplot(true);

            for (int i = 0; i < num_iter; ++i)
            {
                QTest::qWaitForWindowShown(_p.back());
                for (int k = 0; k < (int)residual.size(); ++k)
                    a[k] = fabs(ra[k]);
                _s.back()->setSamples(&residual.freq()[0], amp.data(), residual.size());
                c.simpleClean(ws, cc, residual, 1, gain);
                printf(">>>>> iter = %i\n", i);
            }


            // ====== PLOT CC =================================================
            amp.resize(cc.size());
            for (unsigned i = 0; i < cc.size(); ++i)
                amp[i] = fabs(cc.amp()[i]);

//            _s.push_back(new ScatterPlot);
//            _s.back()->setSamples(&cc.freq()[0], amp.data(), cc.size());
//            _p.push_back(new QwtPlot);
//            _p.back()->setMinimumSize(1000, 500);
//            _p.back()->setVisible(true);
//            _s.back()->attach(_p.back());
//            _p.back()->setAxisScale(QwtPlot::xBottom, -max_freq, max_freq);
//            //_p.back()->setAxisScale(QwtPlot::xBottom, 14.8, 15.2);
//            _s.back()->setPlotStyle(ScatterPlot::DOT);
//            _s.back()->setCurveAttribute(QwtPlotCurve::Fitted, false);
//            _p.back()->setTitle("cc spectrum");

            // ======= CONVOLVE CC WITH GAUSSIAN ==============================
            Spectrum clean;
            c.make_clean_spectrum(cc, clean);

//            amp.resize(clean.size());
//            for (unsigned i = 0; i < clean.size(); ++i)
//                amp[i] = fabs(clean.amp()[i]);
//            _s.push_back(new ScatterPlot);
//            _s.back()->setSamples(&clean.freq()[0], amp.data(), clean.size());
//            _p.push_back(new QwtPlot);
//            _p.back()->setMinimumSize(1000, 500);
//            _p.back()->setVisible(true);
//            _s.back()->attach(_p.back());
//            _p.back()->setAxisScale(QwtPlot::xBottom, -max_freq, max_freq);
////            _p.back()->setAxisScale(QwtPlot::xBottom, 14.8, 15.2);
//            _s.back()->setPlotStyle(ScatterPlot::DOT);
//            _s.back()->setCurveAttribute(QwtPlotCurve::Fitted, false);
//            _p.back()->setTitle("clean spectrum");



            // ======== CC + RESIDUAL ==========================================
//            amp.resize(residual.size());
//            for (unsigned i = 0; i < residual.size(); ++i)
//                amp[i] = fabs(residual.amp()[i] + clean.amp()[i]);
//
//            _s.push_back(new ScatterPlot);
//            _s.back()->setSamples(&residual.freq()[0], amp.data(), residual.size());
//            _p.push_back(new QwtPlot);
//            _p.back()->setMinimumSize(1000, 500);
//            _p.back()->setVisible(true);
//            _s.back()->attach(_p.back());
//            _p.back()->setAxisScale(QwtPlot::xBottom, 0.0, max_freq);
//            _s.back()->setPlotStyle(ScatterPlot::LINE_DOT);
//            _s.back()->setCurveAttribute(QwtPlotCurve::Fitted, false);
//            _p.back()->setTitle("clean + residual spectrum");
        }

    private:
        QVector<QwtPlot*> _p;
        QVector<ScatterPlot*> _s;
};


int main(int argc, char ** argv)
{
    QApplication app(argc, argv);
    QTest_CleanTimeSeries t;
    QTest::qExec(&t, argc, argv);
    return app.exec();
}



#endif // QTEST_TIME_SERIES_H_
